/*     */ package com.zimbra.cs.imap;
/*     */ 
/*     */ import com.google.common.base.Charsets;
/*     */ import com.google.common.base.Preconditions;
/*     */ import com.google.common.primitives.Ints;
/*     */ import java.io.IOException;
/*     */ import java.nio.charset.Charset;
/*     */ import org.apache.mina.core.buffer.IoBuffer;
/*     */ import org.apache.mina.core.session.IoSession;
/*     */ import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
/*     */ import org.apache.mina.filter.codec.ProtocolDecoderException;
/*     */ import org.apache.mina.filter.codec.ProtocolDecoderOutput;
/*     */ import org.apache.mina.filter.codec.RecoverableProtocolDecoderException;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ final class NioImapDecoder
/*     */   extends CumulativeProtocolDecoder
/*     */ {
/*     */   private int maxChunkSize;
/*     */   private int maxLineLength;
/*     */   private long maxLiteralSize;
/*     */   
/*     */   NioImapDecoder()
/*     */   {
/*  40 */     this.maxChunkSize = 1024;
/*  41 */     this.maxLineLength = 1024;
/*  42 */     this.maxLiteralSize = -1L;
/*     */   }
/*     */   
/*  45 */   void setMaxChunkSize(int bytes) { Preconditions.checkArgument(bytes > 0, "Maximum chunk size must be >0 bytes - value given=%s", new Object[] { Integer.valueOf(bytes) });
/*  46 */     this.maxChunkSize = bytes;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   void setMaxLineLength(int bytes)
/*     */   {
/*  56 */     Preconditions.checkArgument(bytes > 0, "Maximum Line length must be >0 bytes - value given=%s", new Object[] { Integer.valueOf(bytes) });
/*  57 */     this.maxLineLength = bytes;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   void setMaxLiteralSize(long bytes)
/*     */   {
/*  67 */     Preconditions.checkArgument(bytes >= -1L, "Maximum Literal size must be >=-1 bytes - value given=%s", new Object[] { Long.valueOf(bytes) });
/*  68 */     if (bytes == 0L) {
/*  69 */       this.maxLiteralSize = -1L;
/*     */     } else {
/*  71 */       this.maxLiteralSize = bytes;
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
/*     */     throws ProtocolDecoderException, IOException, Exception
/*     */   {
/*  86 */     int start = in.position();
/*  87 */     Context ctx = (Context)session.getAttribute(Context.class);
/*  88 */     if (ctx == null) {
/*  89 */       ctx = new Context(null);
/*  90 */       session.setAttribute(Context.class, ctx);
/*     */     }
/*  92 */     byte prev = -1;
/*     */     
/*  94 */     while (in.hasRemaining()) {
/*  95 */       if (ctx.literal >= 0) {
/*  96 */         int len = Ints.min(new int[] { in.remaining(), ctx.literal, this.maxChunkSize });
/*  97 */         if (ctx.overflow) {
/*  98 */           in.skip(len);
/*     */         } else {
/* 100 */           byte[] chunk = new byte[len];
/* 101 */           in.get(chunk);
/* 102 */           out.write(chunk);
/*     */         }
/* 104 */         ctx.literal -= len;
/* 105 */         if (ctx.literal == 0) {
/* 106 */           ctx.literal = -1;
/* 107 */           if (ctx.overflow) {
/* 108 */             ctx.overflow = false;
/* 109 */             dispose(session);
/* 110 */             throw new TooBigLiteralException(ctx.request);
/*     */           }
/*     */         }
/* 113 */         return true;
/*     */       }
/* 115 */       if (in.position() - start > this.maxLineLength) {
/* 116 */         ctx.overflow = true;
/*     */       }
/* 118 */       if (ctx.overflow) {
/* 119 */         if (in.get() == 10) {
/* 120 */           ctx.overflow = false;
/* 121 */           throw new TooLongLineException();
/*     */         }
/* 123 */         return true;
/*     */       }
/*     */       
/* 126 */       byte b = in.get();
/* 127 */       if (b == 10) {
/* 128 */         int pos = in.position();
/* 129 */         int limit = in.limit();
/* 130 */         in.position(start);
/* 131 */         in.limit(prev == 13 ? pos - 2 : pos - 1);
/*     */         
/* 133 */         String line = in.getString(Charsets.ISO_8859_1.newDecoder());
/*     */         
/* 135 */         in.limit(limit);
/* 136 */         in.position(pos);
/*     */         LiteralInfo li;
/*     */         try {
/* 139 */           li = LiteralInfo.parse(line);
/*     */         } catch (IllegalArgumentException e) {
/* 141 */           dispose(session);
/* 142 */           throw new InvalidLiteralFormatException();
/*     */         }
/* 144 */         if ((li != null) && (li.count > 0)) {
/* 145 */           if ((this.maxLiteralSize >= 0L) && (li.count > this.maxLiteralSize)) {
/* 146 */             if (li.isBlocking()) {
/* 147 */               dispose(session);
/* 148 */               throw new TooBigLiteralException(line);
/*     */             }
/* 150 */             ctx.literal = li.count;
/* 151 */             ctx.request = line;
/* 152 */             ctx.overflow = true;
/* 153 */             return true;
/*     */           }
/*     */           
/* 156 */           ctx.literal = li.count;
/* 157 */           ctx.request = line;
/*     */         }
/* 159 */         out.write(line);
/*     */         
/*     */ 
/* 162 */         return true;
/*     */       }
/* 164 */       prev = b;
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/* 170 */     in.position(start);
/* 171 */     return false;
/*     */   }
/*     */   
/*     */   private static final class Context {
/* 175 */     boolean overflow = false;
/* 176 */     int literal = -1;
/*     */     String request;
/*     */   }
/*     */   
/*     */   static final class TooLongLineException extends RecoverableProtocolDecoderException
/*     */   {
/*     */     private static final long serialVersionUID = -7284634822713651847L;
/*     */     
/*     */     public String getMessage() {
/* 185 */       return "maximum line length exceeded";
/*     */     }
/*     */   }
/*     */   
/*     */   static final class TooBigLiteralException extends RecoverableProtocolDecoderException
/*     */   {
/*     */     private static final long serialVersionUID = 4272855594291614583L;
/*     */     private String request;
/*     */     
/*     */     TooBigLiteralException(String req) {
/* 195 */       this.request = req;
/*     */     }
/*     */     
/*     */     public String getRequest() {
/* 199 */       return this.request;
/*     */     }
/*     */     
/*     */     public String getMessage()
/*     */     {
/* 204 */       return "maximum literal size exceeded";
/*     */     }
/*     */   }
/*     */   
/*     */   static final class InvalidLiteralFormatException extends ProtocolDecoderException
/*     */   {
/*     */     private static final long serialVersionUID = 7224987995979809371L;
/*     */     
/*     */     public String getMessage() {
/* 213 */       return "invalid literal format";
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/imap/NioImapDecoder.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */